<!--
 * @Author       : xiangmin
 * @File         : 通用表单---搜索新建都是可以用的
 * @Date         : 2022-11-21 09:49:18
 * @LastEditors  : xiangmin
 * @LastEditTime : 2024-09-19 15:26:54
-->
<template>
	<a-form
		:model="model"
		ref="formRef"
		v-bind="$attrs"
	>
		<a-row
			:gutter="gutter"
			:class="[search && 'search']"
		>
			<template
				v-for="(item, index) in fields"
				:key="index"
			>
				<a-col
					:span="item.span ?? span"
					v-show="index < expandNum || expand"
					v-if="item.renderDepend?.({ model, getField }) ?? true"
				>
					<form-element
						:field-item="item"
						:submit="search?.query"
						:model="model"
						:getField="getField"
					>
						<template
							v-for="(_, name) in $slots"
							v-slot:[name]
						>
							<slot :name="name"></slot>
						</template>
					</form-element>
				</a-col>
			</template>
			<SearchButtonGroup
				v-if="search"
				v-model:expand="expand"
				:expandVisible="expandNum < fields?.length"
				:search="search"
			/>
			<slot></slot>
		</a-row>
	</a-form>
</template>

<script setup lang="ts">
import type { FormInstance } from 'ant-design-vue'
import FormElement from './Element.vue'
import SearchButtonGroup from './SearchButtonGroup.vue'

const {
	fields = [],
	span = 6,
	gutter = 20,
	expandNum = Infinity
} = defineProps<{
	model: Record<string, any>
	fields: FormFields
	span?: number
	expandNum?: number
	gutter?: number
	search?: {
		loading?: boolean
		query?: () => void
		reset?: () => void
	}
}>()

/**
 * @description 展开收起按钮
 */
const expand = defineModel<boolean>('expand', { default: false, required: false })

/**
 * 获取表单的具体项
 */
const getField = (name: string) => fields.find(item => item.field === name) as FormFields[0]

const formRef = ref<FormInstance>()
type Expose = {
	clearValidate: Function
	resetFields: Function
	scrollToField: Function
	validate: Function
	validateFields: Function
	getField: Function
}
const expose: Expose = {} as Expose
onMounted(() => {
	const entries = Object.entries(formRef.value as FormInstance)
	// @ts-ignore
	entries.getField = getField
	for (let [method, fn] of entries) {
		expose[method] = fn
	}
})
defineExpose(expose)
</script>

<style scoped lang="less">
.search {
	gap: 18px 0;

	:deep(.ant-form-item) {
		margin-bottom: 0;
	}
}
</style>
